<!--
 * @Description: Stay hungry，Stay foolish
 * @Author: ''
 * @Date: 2023-10-10 22:23:22
 * @LastEditTime: 2023-10-10 23:30:36
 * @LastEditors: ''
-->
<template>
  <div class="haloe-calendar">
    <div class="haloe-calendar-header" v-if="showHeader">
      <slot name="header">
        <div class="haloe-calendar-header-title">
          <slot name="headerTitle">{{ headerTitle }}</slot>
        </div>
        <div class="haloe-calendar-header-action">
          <template v-if="headerType === 'simple'">
            <ButtonGroup>
              <Button
                @click="handlePrev"
              ><Icon
                type="chevron-left"
              /></Button>
              <Button @click="handleToday">{{ locale.today }}</Button>
              <Button
                @click="handleNext"
              ><Icon
                type="chevron-right"
              /></Button>
            </ButtonGroup>
            <RadioGroup
              v-if="!hideType"
              v-model="mode"
              type="button"
              class="haloe-ml"
              @on-change="handleChangeType"
            >
              <Radio label="month">{{ locale.type.month }}</Radio>
              <Radio label="year">{{ locale.type.year }}</Radio>
            </RadioGroup>
          </template>
          <template v-else-if="headerType === 'full'"> </template>
        </div>
      </slot>
    </div>
    <div class="haloe-calendar-body">
      <CalendarMonth v-if="mode === 'month'" :date="currentValue">
        <template #month="{ date, data }">
          <slot :date="date" :data="data" name="month"></slot>
        </template>
      </CalendarMonth>
      <CalendarYear v-else-if="mode === 'year'" :date="currentValue">
        <template #year="{ month, data }">
          <slot :month="month" :data="data" name="year"></slot>
        </template>
      </CalendarYear>
    </div>
  </div>
</template>

<script setup>
defineOptions({
  name: 'Calendar',
})

import ButtonGroup from '../button/button-group.vue'
import Button from '../button/button.vue'
import RadioGroup from '../radio/radio-group.vue'
import Radio from '../radio/radio.vue'
import Icon from '../icon/icon.vue'

import dayjs from 'dayjs'
import { oneOf } from '../../utils/assist.js'
import CalendarMonth from './month'
import CalendarYear from './year'

import { ref, watch, computed, provide } from 'vue'
const emits = defineEmits([
  'on-type-change',
  'on-prev',
  'on-next',
  'on-today',
  'on-change',
  'update:modelValue',
  'on-cell-click',
  'on-cell-contextmenu',
])

const props = defineProps({
  modelValue: {
    type: [Date, String, Number],
  },
  // 视图类型，月、年
  type: {
    validator(value) {
      return oneOf(value, ['month', 'year'])
    },
    default: 'month',
  },
  cellHeight: {
    type: Number,
    default: 100,
  },
  // 是否显示顶部
  showHeader: {
    type: Boolean,
    default: true,
  },
  // 顶部菜单类型
  headerType: {
    validator(value) {
      return oneOf(value, ['simple', 'full'])
    },
    default: 'simple',
  },
  // 周起始日
  firstDayOfWeek: {
    validator(value) {
      return oneOf(value, [1, 2, 3, 4, 5, 6, 7])
    },
    default: 1,
  },
  hideType: {
    type: Boolean,
    default: false,
  },
  // 默认文案
  locale: {
    type: Object,
    default() {
      return {
        today: '今天',
        type: {
          month: '月',
          year: '年',
        },
        weekDays: ['日', '一', '二', '三', '四', '五', '六'],
        months: [
          '1月',
          '2月',
          '3月',
          '4月',
          '5月',
          '6月',
          '7月',
          '8月',
          '9月',
          '10月',
          '11月',
          '12月',
        ],
      }
    },
  },
})

const value = props.modelValue ? props.modelValue : new Date()
let currentValue = ref(dayjs(value))
let mode = ref(props.type)

watch(
  () => props.modelValue,
  (val) => {
    const value = val ? val : new Date()
    currentValue.value = dayjs(value)
  }
)

watch(
  () => props.type,
  (val) => {
    mode.value = val
  }
)
// eslint-disable-next-line vue/return-in-computed-property
const headerTitle = computed(() => {
  if (mode.value === 'month') {
    return currentValue.value.format('YYYY 年 M 月')
  } else if (mode.value === 'year') {
    return currentValue.value.format('YYYY 年')
  }
})

const handleChangeType = (type) => {
  emits('on-type-change', type)
}

const handleChangeDate = (val) => {
  currentValue.value = val
  const date = new Date(val.format('YYYY-MM-DD'))
  emits('update:modelValue', date)
  emits('on-change', date)
}

const handlePrev = () => {
  const firstDate = currentValue.value.format('YYYY-MM-01')
  let prevDate
  if (mode.value === 'month') {
    prevDate = dayjs(firstDate).subtract(1, 'month')
  } else if (mode.value === 'year') {
    prevDate = dayjs(firstDate).subtract(1, 'year')
  }
  handleChangeDate(prevDate)
  emits('on-prev')
}
const handleNext = () => {
  const firstDate = currentValue.value.format('YYYY-MM-01')
  let nextDate
  if (mode.value === 'month') {
    nextDate = dayjs(firstDate).add(1, 'month')
  } else if (mode.value === 'year') {
    nextDate = dayjs(firstDate).add(1, 'year')
  }
  handleChangeDate(nextDate)
  emits('on-next')
}
const handleToday = () => {
  const nowDate = dayjs(new Date())
  const today = nowDate.format('YYYY-MM-DD')
  const _currentValue = currentValue.value.format('YYYY-MM-DD')
  if (today !== _currentValue) {
    handleChangeDate(nowDate)
  }
  emits('on-today')
}

const onCellClick = (data) => {
  emits('on-cell-click', data)
}

const onCellContextmenu = (date) => {
  emits('on-cell-contextmenu', date)
}

provide('CalendarInstance', {
  onCellClick,
  onCellContextmenu,
  handleChangeDate,
  firstDayOfWeek: computed(() => props.firstDayOfWeek),
  locale:computed(()=>props.locale),
  cellHeight:computed(()=>props.cellHeight)
})
</script>
